/**
 * create by zhangpu
 * date:2015年3月12日
 */
package com.acooly.module.openapi.client.provider.fuiou.marshall;

import com.acooly.core.utils.Reflections;
import com.acooly.core.utils.Strings;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.marshal.ApiUnmarshal;
import com.acooly.module.openapi.client.api.message.MessageFactory;
import com.acooly.module.openapi.client.provider.fuiou.FuiouConstants;
import com.acooly.module.openapi.client.provider.fuiou.domain.FuiouResponse;
import com.acooly.module.openapi.client.provider.fuiou.support.FuiouAlias;
import com.acooly.module.openapi.client.provider.fuiou.support.FuiouRespCodes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;

/**
 * 跳转接口 同步跳回报文解析
 *
 * @author zhangpu
 */
@Service
public class FuiouReturnUnmarshall extends FuiouMarshallSupport
        implements ApiUnmarshal<FuiouResponse, Map<String, String>> {

    private static final Logger logger = LoggerFactory.getLogger(FuiouReturnUnmarshall.class);
    
    @Resource(name = "fuiouMessageFactory")
    private MessageFactory messageFactory;

    @SuppressWarnings("unchecked")
    @Override
    public FuiouResponse unmarshal(Map<String, String> message, String serviceName) {
        try {
            logger.info("同步通知{}", message);
            String signature = message.get("signature");
            String plain = getWaitForSign(message);
            getSignerFactory().getSigner(FuiouConstants.SIGNER_KEY).verify(signature, getKeyPair(), plain);
            return doUnmarshall(message, serviceName);
        } catch (Exception e) {
            throw new ApiClientException("异步通知 解析失败:" + e.getMessage());
        }

    }

    protected FuiouResponse doUnmarshall(Map<String, String> message, String serviceName) {
        FuiouResponse response = (FuiouResponse) messageFactory.getReturn(serviceName);
        Set<Field> fields = Reflections.getFields(response.getClass());
        String key = null;
        for (Field field : fields) {
            FuiouAlias fuiouAlias = field.getAnnotation(FuiouAlias.class);
            if (fuiouAlias == null) {
                continue;
            }
            key = fuiouAlias.value();
            if (Strings.isBlank(key)) {
                key = field.getName();
            }
            Reflections.invokeSetter(response, field.getName(), message.get(key));
        }
        response.setService(serviceName);
        if (Strings.isNotBlank(response.getRespCode())) {
            response.setMessage(FuiouRespCodes.getMessage(response.getRespCode()));
        }
        return response;
    }

    public void setMessageFactory(MessageFactory messageFactory) {
        this.messageFactory = messageFactory;
    }

}
